// -*- coding: utf-8 -*- 
package PICUtils;

import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageEncoder;
import com.sun.media.jai.codec.JPEGEncodeParam;

import javax.media.jai.JAI;
import javax.media.jai.RenderedOp;
import java.io.*;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.FileImageInputStream;
import javax.media.jai.operator.TransposeDescriptor;
import java.awt.image.renderable.ParameterBlock;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Hashtable;
import java.util.NoSuchElementException;
import java.util.Vector;
//使用java库对tiff文件进行操作
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.IndexColorModel;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;


import javax.media.jai.ColorCube;
import javax.media.jai.ImageLayout;
import javax.media.jai.Interpolation;
import javax.media.jai.KernelJAI;
import javax.media.jai.LookupTableJAI;

import com.sun.media.jai.codec.PNGEncodeParam;
import com.sun.media.jai.codec.TIFFEncodeParam;
import com.sun.media.jai.codec.TIFFField;
import com.sun.media.jai.codecimpl.TIFFImageDecoder;

//详细过程：

/**
 * 图像处理工具类
 */
@SuppressWarnings("ALL")
public class PICUtils {
    /**
     * 将 tiff 转换 jpg 格式
     *
     * @param filePath
     * @return
     */
    public static String tiffTuanJPG(String filePath) {
        String format = filePath.substring(filePath.lastIndexOf(".") + 1);
        String turnJpgFile = filePath.replace("tiff", "jpg");
        if (format.equals("tiff")) {
            File fileTiff = new File(turnJpgFile);
            if (fileTiff.exists()) {
                System.out.println("该tiff文件已经转换为 JPG 文件：" + turnJpgFile);
                return turnJpgFile;
            }
            RenderedOp rd = JAI.create("fileload", filePath);//读取iff文件
            OutputStream ops = null;
            try {
                ops = new FileOutputStream(turnJpgFile);
                //文件存储输出流
                JPEGEncodeParam param = new JPEGEncodeParam();
                ImageEncoder image = ImageCodec.createImageEncoder("JPEG", ops, param); //指定输出格式
                image.encode(rd);
                //解析输出流进行输出
                ops.close();
                System.out.println("tiff转换jpg成功:" + filePath);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return turnJpgFile;
    }


    public static void main(String[] args) throws IOException {
        ImageReader reader = null;
        FileImageInputStream fis = null;
        //C:\Users\86156\Desktop\aod.tiff
        //E:\保定/aod.tiff
        File file = new File("C:\\Users\\86156\\Desktop\\aod.tiff");
        Object[] src = readTiff(file);
        if (src == null) System.out.println("读取失败");
        reader = (ImageReader) src[0];
        fis = (FileImageInputStream) src[1];
        System.out.println(reader);
        System.out.println(fis);
        long[] dpiData = new long[]{1, 1};
        BufferedImage img = loadTiff(file, dpiData);
        System.out.println(img.getColorModel());
        if (img == null) System.out.println("空值");
        //获取图片的长宽和最小值
        int width = img.getWidth();
        int height = img.getHeight();
        int minx = img.getMinX();
        int miny = img.getMinY();
        int rgb[] = new int[width * height];
        int a[][] = new int[img.getWidth()][img.getHeight()];
        /*for (int i = minx; i < img.getWidth(); i++) {
            for (int j = miny; j < img.getHeight(); j++) {
                    a[i][j] = img.getRGB(i, j);
            }
        }
        for (int i = 0; i < img.getWidth(); i++) {
            for (int j = 0; j < img.getHeight(); j++) {
                System.out.print(a[i][j]);
            }
            System.out.println();
        }*/
        for (int i = minx; i < width; i++) {
            for (int j = miny; j < height; j++) {
                int pixel = img.getRGB(i, j); // 下面三行代码将一个数字转换为RGB数字
                rgb[0] = (pixel & 0xff0000) >> 16;
                rgb[1] = (pixel & 0xff00) >> 8;
                rgb[2] = (pixel & 0xff);
                System.out.print("i=" + i + ",j=" + j + ":(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ")");
            }
            System.out.println();
        }
        System.out.println(img.getRGB(155, 88));

        System.out.println("-----------------------------");
        //img.getRGB(0,0,width-1,height-1 , rgb,0,width);

        File pfile = new File("E:/挑战杯/市数据/保定/aod_tiff.png");
        //boolean b = makeDispPage(file,0,pfile);
        //System.out.println(b);


    }

    //读取tiff文件到 ImageReader Object[0]：ImageReader ,Object[1]:FileImageInputStream
    private static Object[] readTiff(File tifFile) {
        ImageReader reader = null;
        FileImageInputStream fis = null;
        Object[] res = null;
        try {
            reader = ImageIO.getImageReadersByFormatName("tiff").next();
            fis = new FileImageInputStream(tifFile);
            reader.setInput(fis);
            res = new Object[]{reader, fis};
        } catch (NoSuchElementException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        }
        return res;
    }

    //获取tiff dpi
    public static long[] getTiffDPI(ImageReader reader, int index) {
        long[] dpi = new long[2];
        IIOMetadata meta = null;
        try {
            meta = reader.getImageMetadata(index);
            org.w3c.dom.Node n = meta.getAsTree("javax_imageio_1.0");
            n = n.getFirstChild();

            while (n != null) {

                if (n.getNodeName().equals("Dimension")) {

                    org.w3c.dom.Node n2 = n.getFirstChild();

                    while (n2 != null) {

                        if (n2.getNodeName().equals("HorizontalPixelSize")) {

                            org.w3c.dom.NamedNodeMap nnm = n2.getAttributes();

                            org.w3c.dom.Node n3 = nnm.item(0);

                            float hps = Float.parseFloat(n3.getNodeValue());

                            dpi[0] = Math.round(25.4f / hps);

                        }

                        if (n2.getNodeName().equals("VerticalPixelSize")) {

                            org.w3c.dom.NamedNodeMap nnm = n2.getAttributes();

                            org.w3c.dom.Node n3 = nnm.item(0);

                            float vps = Float.parseFloat(n3.getNodeValue());

                            dpi[1] = Math.round(25.4f / vps);
                        }

                        n2 = n2.getNextSibling();

                    }

                }

                n = n.getNextSibling();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return dpi;
    }


    //读取tiff文件到 BufferedImage
    private static BufferedImage loadTiff(File tifFile, long[] dpiData) {

        ImageReader reader = null;
        FileImageInputStream fis = null;
        BufferedImage res = null;
        try {
            Object[] src = readTiff(tifFile);
            if (src == null) {
                return null;
            }
            reader = (ImageReader) src[0];
            fis = (FileImageInputStream) src[1];
            if (reader != null) {
                int numPages = reader.getNumImages(true);
                if (numPages > 0) {
                    long[] dpiArr = getTiffDPI(reader, 0);
                    dpiData[0] = dpiArr[0];
                    dpiData[1] = dpiArr[1];
                    res = reader.read(0);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                reader.dispose();
            }

            if (fis != null) {
                try {
                    fis.flush();
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }


        }
        return res;
    }

    /**
     * 从tiff文件生成原始像素大小tiff文件
     *
     * @param fTiff  源tiff文件
     * @param decDir tiff目标路径,目标文件将会以0001.tif,0002.tif...置于此路径下
     * @return true表示成功, false表示失败
     */
    public static boolean makeSingleTif(File fTiff, File decDir) {
        boolean bres = true;
        ImageReader reader = null;
        FileImageInputStream fis = null;
        try {
            reader = ImageIO.getImageReadersByFormatName("tiff").next();
            fis = new FileImageInputStream(fTiff);
            reader.setInput(fis);

            int numPages = reader.getNumImages(true);
            for (int i = 0; i < numPages; i++) {

                long[] dpiData = getTiffDPI(reader, i);
                BufferedImage bi = reader.read(i);

                File tif = new File(decDir.getPath() + File.separator + String.format("%1$04d", i + 1) + ".tif");
                bres = createTiff(tif, new RenderedImage[]{bi}, dpiData, false);

            }

        } catch (Exception e) {
            e.printStackTrace();
            bres = false;

        } finally {

            if (reader != null) {
                reader.dispose();
            }

            if (fis != null) {
                try {
                    fis.flush();
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }


        return bres;
    }

    /**
     * 合并多个Tiff文件成一个多页Tiff文件
     *
     * @param fTiff  目标tiff文件
     * @param tifDir 源tiff文件路径,tiff文件必须以0001.tif,0002.tif...置于此路径下
     * @return true表示成功, false表示失败
     */
    static public boolean mergeTiff(File fTiff, File tifDir) {

        boolean bres = true;
        ImageReader reader = null;
        FileImageInputStream fis = null;
        Vector<BufferedImage> biV = new Vector<BufferedImage>();
        File[] fs = tifDir.listFiles();
        long[] dpi = null;
        for (File f : fs) {
            String fileName = f.getName();
            if (!fileName.endsWith(".tif")) {
                continue;
            }
            try {
                reader = ImageIO.getImageReadersByFormatName("tiff").next();
                fis = new FileImageInputStream(f);
                reader.setInput(fis);
                biV.add(reader.read(0));
                if (dpi == null) {
                    dpi = getTiffDPI(reader, 0);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (reader != null) {
                    reader.dispose();
                }

                if (fis != null) {
                    try {
                        fis.flush();
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

            }
        }

        RenderedImage[] biArr = new RenderedImage[biV.size()];
        for (int i = 0; i < biArr.length; i++) {
            biArr[i] = biV.get(i);
        }

        bres = createTiff(fTiff, biArr, dpi, false);


        return bres;
    }

    //获取tiff文件的页数
    public static int getTiffPages(File tifFile) {
        ImageReader reader = null;
        FileImageInputStream fis = null;
        int numpages = 0;
        try {
            Object[] src = readTiff(tifFile);
            if (src == null) {
                return 0;
            }
            reader = (ImageReader) src[0];
            fis = (FileImageInputStream) src[1];
            if (reader != null) {
                numpages = reader.getNumImages(true);
            }

        } catch (Exception e) {
            e.printStackTrace();

        } finally {

            if (reader != null) {
                reader.dispose();
            }

            if (fis != null) {
                try {
                    fis.flush();
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }


        }
        return numpages;
    }


    /**
     * 生成tiff原始dpi的png
     *
     * @param fTiff   用于生成文件的tif文件
     * @param decFile 目标png
     * @param tifIdx  tif文件页码索引，从0开始
     */
    public static void makePrintPngFromTifByScal(File fTiff, File decFile, int tifIdx) {

        long d = System.currentTimeMillis();
        FileOutputStream os = null;
        ImageReader reader = null;

        FileImageInputStream fis = null;
        try {

            Object[] src = readTiff(fTiff);
            if (src == null) {
                return;
            }
            reader = (ImageReader) src[0];
            fis = (FileImageInputStream) src[1];


            if (reader != null) {
                int numPages = reader.getNumImages(true);
                if (numPages > 0 && tifIdx < numPages) {
                    long[] dpiData = getTiffDPI(reader, tifIdx);
                    BufferedImage img = reader.read(tifIdx);


                    double meter2inchRatio = 1d / 0.0254d;
                    int dimX = (int) (dpiData[0] * meter2inchRatio) + 1;
                    int dimY = (int) (dpiData[0] * meter2inchRatio) + 1;

                    int iYScal = (Math.abs(dpiData[0] - dpiData[1]) <= 10) ? 1 : 2;

                    int width = img.getWidth();
                    int height = img.getHeight() * iYScal;


                    //200 * 210 /25.4 ---- 200 * 297 /25.4

                    double whScal = 230.0 / 238.0;
                    double realScal = (double) width / (double) height;


                    int drawPtX = 0;    //图像起始x位置
                    int drawPtY = 0;    //图像起始Y位置
                    int newW = 230;
                    int newH = 238;


                    if (realScal < whScal) {    // 以高度为缩放基准
                        newW = (int) (238.0 * realScal);
                        drawPtX = (230 - newW) / 2;
                    } else {
                        newH = (int) (230 / realScal);
                        drawPtY = (238 - newH) / 2;
                    }

//System.out.println("width=" + width + ", height=" + height + ", newW=" + newW + ", newH=" + newH + ", dimX=" + dimX + ", dimY=" + dimY);
                    BufferedImage decImg = new BufferedImage(230, 238, BufferedImage.TYPE_3BYTE_BGR);
                    Graphics2D g2 = decImg.createGraphics();
                    g2.setColor(Color.white);
                    g2.fillRect(0, 0, 230, 238);

                    g2.drawImage(img.getScaledInstance(newW, newH, Image.SCALE_SMOOTH), drawPtX, drawPtY, null);


                    PNGEncodeParam paramEnc = PNGEncodeParam.getDefaultEncodeParam(decImg);
                    paramEnc.setPhysicalDimension(dimX, dimY, 1);
                    os = new FileOutputStream(decFile);
                    JAI.create("encode", decImg, os, "PNG", paramEnc);
                    os.flush();
                    os.close();

                }


            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

            if (reader != null) {
                reader.dispose();
            }
            if (fis != null) {
                try {
                    fis.flush();
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {

                    os.flush();
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

        System.out.println(("----make print Pngs time----" + (System.currentTimeMillis() - d) + "ms"));

    }


    /**
     * 从tiff文件生成用于显示的一页png
     *
     * @param fTiff   源tiff文件
     * @param pageIdx 页号,从0开始
     * @param dDecPng 目标png文件
     * @return true表示成功, false表示失败
     */
    static public boolean makeDispPage(File fTiff, int pageIdx, File dDecPng) {
        long d = System.currentTimeMillis();

        ImageReader reader = null;
        FileImageInputStream fis = null;
        boolean bres = false;
        try {
            Object[] src = readTiff(fTiff);
            if (src == null) {
                return false;
            }
            reader = (ImageReader) src[0];
            fis = (FileImageInputStream) src[1];
            if (reader != null) {
                int numPages = reader.getNumImages(true);
                if (numPages > 0) {
                    if (pageIdx >= 0 && (pageIdx < numPages)) {
                        long[] dpi = getTiffDPI(reader, pageIdx);
                        if (dpi != null && dpi.length == 2) {
                            if (dpi[0] <= 0) dpi[0] = 1;
                            if (dpi[1] <= 0) dpi[1] = 1;
                            double dXFac = 1 / dpi[0];
                            double dYFac = 1 / dpi[1];
                            BufferedImage img = reader.read(pageIdx);
                            RenderedImage decImg = ScaleImg(img, dXFac, dYFac);
                            ImageIO.write(decImg, "png", dDecPng);
                            bres = true;
                        }
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();

        } finally {

            if (reader != null) {
                reader.dispose();
            }

            if (fis != null) {
                try {
                    fis.flush();
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }


        }
        System.out.println(("----make disp png by IO use time:" + (System.currentTimeMillis() - d) + "ms"));
        return bres;
    }


    /**
     * 从tiff生成缩略图
     *
     * @param fTiff
     * @param decDir
     * @return
     */
    public static boolean makeThumbsFromTiff(File fTiff, File decDir) {
        long d = System.currentTimeMillis();
        int numPages = 0;
        int thumbWidth = 188;
        int thumbHeight = 254;

        ImageReader reader = null;
        FileImageInputStream fis = null;
        boolean bres = true;
        try {
            Object[] src = readTiff(fTiff);
            if (src == null) {
                return false;
            }
            reader = (ImageReader) src[0];
            fis = (FileImageInputStream) src[1];

            if (reader != null) {
                numPages = reader.getNumImages(true);
                if (numPages > 0) {

                    for (int i = 0; i < numPages; i++) {
                        long[] dpiData = getTiffDPI(reader, i);
                        BufferedImage img = reader.read(i);
                        int ht = img.getHeight();
                        int wid = img.getWidth();
                        float fsc = (float) dpiData[0] / (float) dpiData[1];
                        if (Math.abs(fsc - 1.0) > 0.2) {
                            if (fsc < 1) {
                                wid = (int) (wid / fsc);
                            } else {
                                ht = (int) (ht * fsc);
                            }
                        }

                        double realScal = (double) wid / (double) ht;
                        double whScal = (double) thumbWidth / (double) thumbHeight;

                        int newW = thumbWidth;
                        int newH = thumbHeight;

                        if (realScal < whScal) {    // 以高度为缩放基准
                            newW = (int) (thumbHeight * realScal);
                        } else {
                            newH = (int) (thumbWidth / realScal);
                        }
                        int x = (thumbWidth - newW) / 2;
                        int y = (thumbHeight - newH) / 2;

                        System.out.println(newW + "," + newH + "," + x + "," + y);
                        BufferedImage decImg = new BufferedImage(thumbWidth, thumbHeight, BufferedImage.TYPE_3BYTE_BGR);
                        Graphics2D g2 = (Graphics2D) decImg.createGraphics();
                        g2.setColor(new Color(160, 160, 160));
                        g2.fillRect(0, 0, thumbWidth, thumbHeight);
                        g2.drawImage(img.getScaledInstance(newW, newH, Image.SCALE_SMOOTH), x, y, null);


                        File decPng = new File(decDir.getPath() + File.separator + String.format("%1$04d", i + 1) + ".png");
                        ImageIO.write(decImg, "png", decPng);

                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            bres = false;
        } finally {

            if (reader != null) {
                reader.dispose();
            }
            if (fis != null) {
                try {
                    fis.flush();
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        System.out.println(("----make Thumbs time----" + (System.currentTimeMillis() - d) + "ms") + "-----make pages---" + numPages);
        return bres;
    }


    /**
     * 旋转Tiff文件
     *
     * @param fTiff 要旋转的tiff文件
     * @param angle 旋转角度: 90,180,270
     * @return true表示成功, false表示失败
     */
    static public boolean RotateTiff(File fTiff, double angle) {
        FileOutputStream out = null;
        File fTiffTmp = new File(fTiff.getPath() + ".tmpABCD.tmp");
//		File fTiffTmp = new File("c:\\io.tif");
        long d = System.currentTimeMillis();
        ImageReader reader = null;
        FileImageInputStream fis = null;

        boolean bres = false;
        try {
            Object[] src = readTiff(fTiff);
            if (src == null) {
                return false;
            }
            reader = (ImageReader) src[0];
            fis = (FileImageInputStream) src[1];
            if (reader != null) {
                int numPages = reader.getNumImages(true);
                if (numPages > 0) {
                    long[] dpiData = getTiffDPI(reader, 0);
                    BufferedImage bi = reader.read(0);
                    RenderedImage dec1 = RotateImg(bi, angle);
                    bres = createTiff(fTiffTmp, new RenderedImage[]{dec1}, dpiData, false);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (reader != null) {
            reader.dispose();
        }
        if (fis != null) {
            try {
                fis.flush();
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (bres && fTiffTmp.exists()) {
            fTiff.delete();
            fTiffTmp.renameTo(fTiff);
        }
        System.out.println(("----rotate tiff by IO use time:" + (System.currentTimeMillis() - d) + "ms"));
        return bres;
    }


    /**
     * 在Tiff图像上进行盖章操作
     *
     * @param fTiff 单页tiff文件
     * @param stamp 图章tiff文件
     * @param pt    盖章位置
     * @return true表示成功, false表示失败
     */
    static public boolean DrawStamp(File fTiff, File stamp, Point pt) {


        ImageReader reader = null;
        FileImageInputStream fis = null;
        boolean bRes = false;
        try {
            Object[] src = readTiff(fTiff);
            if (src == null) {
                return false;
            }
            reader = (ImageReader) src[0];
            fis = (FileImageInputStream) src[1];
            if (reader != null) {
                int numPages = reader.getNumImages(true);

                if (numPages > 0) {
                    long[] dpiDataSrc = getTiffDPI(reader, 0);

                    BufferedImage imageDec = reader.read(0);

                    long[] dpiData = new long[]{200, 200};
                    BufferedImage img = loadTiff(stamp, dpiData);
                    if (img == null) return false;

                    if (java.lang.Math.abs(dpiData[0] - dpiDataSrc[0]) > 10 || java.lang.Math.abs(dpiData[1] - dpiDataSrc[1]) > 10) {
                        double factorX = (double) dpiDataSrc[0] / (double) dpiData[0];
                        double factorY = (double) dpiDataSrc[1] / (double) dpiData[1];
                        img = convertRenderedImage(ScaleImg(img, factorX, factorY));
                    }

                    imageDec = DoStamp(imageDec, img, pt);

                    bRes = createTiff(fTiff, new RenderedImage[]{imageDec}, dpiDataSrc, false);

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                reader.dispose();
            }
            if (fis != null) {
                try {
                    fis.flush();
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return bRes;
    }


    private static BufferedImage convertRenderedImage(RenderedImage img) {

        if (img instanceof BufferedImage) {
            return (BufferedImage) img;
        }

        ColorModel cm = img.getColorModel();

        int width = img.getWidth();
        int height = img.getHeight();
        WritableRaster raster = cm.createCompatibleWritableRaster(width, height);

        boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
        Hashtable<String, Object> properties = new Hashtable<String, Object>();
        String[] keys = img.getPropertyNames();
        if (keys != null) {
            for (int i = 0; i < keys.length; i++) {
                try {
                    properties.put(keys[i], img.getProperty(keys[i]));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        BufferedImage result = new BufferedImage(cm, raster, isAlphaPremultiplied, properties);
        img.copyData(raster);


        return result;
    }

    private static RenderedImage RGBToBilevel(RenderedImage srcImg, boolean isErrorDiffusion) {
        // Load the ParameterBlock for the dithering operation
        // and set the operation name.
        RenderedImage res = null;
        ParameterBlock pb = new ParameterBlock();
        pb.addSource(srcImg);
        String opName = null;
        if (isErrorDiffusion) {
            opName = "errordiffusion";
            LookupTableJAI lut = new LookupTableJAI(new byte[][]{{(byte) 0x00, (byte) 0xff}, {(byte) 0x00, (byte) 0xff}, {(byte) 0x00, (byte) 0xff}});
            pb.add(lut);
            pb.add(KernelJAI.ERROR_FILTER_FLOYD_STEINBERG);
        } else {
            opName = "ordereddither";
            ColorCube cube = ColorCube.createColorCube(DataBuffer.TYPE_BYTE, 0, new int[]{2, 2, 2});
            pb.add(cube);
            pb.add(KernelJAI.DITHER_MASK_443);
        }
        // Create a layout containing an IndexColorModel which maps
        // zero to zero and unity to 255; force SampleModel to be bilevel.
        ImageLayout layout = new ImageLayout();
        byte[] map = new byte[]{(byte) 0x00, (byte) 0xff};
        ColorModel cm = new IndexColorModel(1, 2, map, map, map);
        layout.setColorModel(cm);
        SampleModel sm = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, srcImg.getWidth(), srcImg.getHeight(), 1);
        layout.setSampleModel(sm);
        // Create a hint containing the layout.
        RenderingHints hints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, layout);
        // Dither the image.
        res = JAI.create(opName, pb, hints);
        return res;

    }

    private static RenderedImage RotateImg(RenderedImage img, double angle) {
        ParameterBlock params = new ParameterBlock();
        params.addSource(img);
        if (angle == 90.0) {
            params.add(TransposeDescriptor.ROTATE_90);
            return JAI.create("Transpose", params, null);
        } else if (angle == 180.0) {
            params.add(TransposeDescriptor.ROTATE_180);
            return JAI.create("Transpose", params, null);
        } else if (angle == 270.0) {
            params.add(TransposeDescriptor.ROTATE_270);
            return JAI.create("Transpose", params, null);
        }
        Interpolation interp = Interpolation.getInstance(Interpolation.INTERP_BILINEAR);
        params.add(0.0F);
        params.add(0.0F);
        params.add((float) java.lang.Math.toRadians(angle));
        params.add(interp);
        return JAI.create("rotate", params, null);
    }


    private static RenderedImage ScaleImg(RenderedImage img, double factorX, double factorY) {
        BufferedImage imgB = convertRenderedImage(img);
        int iType = imgB.getType();
        if (iType == BufferedImage.TYPE_BYTE_BINARY || iType == BufferedImage.TYPE_CUSTOM || iType == BufferedImage.TYPE_BYTE_INDEXED)
            iType = BufferedImage.TYPE_3BYTE_BGR;
        double newWidth = img.getWidth() * factorX;
        double newHeight = img.getHeight() * factorX;
        System.out.println(img.getWidth());
        System.out.println(img.getHeight());
        BufferedImage bufferedImage = new BufferedImage((int) newWidth, (int) newHeight, iType);
        bufferedImage.getGraphics().drawImage(imgB.getScaledInstance((int) newWidth, (int) newHeight, Image.SCALE_SMOOTH), 0, 0, null);
        return bufferedImage;
    }

    private static RenderedImage DoAndImg(RenderedImage img1, RenderedImage img2) {
        ParameterBlock params = new ParameterBlock();
        params.addSource(img1);
        params.addSource(img2);
        return JAI.create("And", params, null);

    }

    private static RenderedImage DoOrImg(RenderedImage img1, RenderedImage img2) {
        ParameterBlock params = new ParameterBlock();
        params.addSource(img1);
        params.addSource(img2);
        return JAI.create("Or", params, null);

    }


    private static BufferedImage DoStamp(BufferedImage image1, BufferedImage image2, Point pt) throws Exception {


        int imgTp1 = image1.getType();
        int imgTp2 = image2.getType();
        System.out.println("imgTp1=" + imgTp1 + ", imgTp2=" + imgTp2 + ", BufferedImage.TYPE_BYTE_BINARY=" + BufferedImage.TYPE_BYTE_BINARY);
        if (BufferedImage.TYPE_BYTE_BINARY == imgTp1 && imgTp2 != BufferedImage.TYPE_BYTE_BINARY) {

            BufferedImage tmpImg = new BufferedImage(image1.getWidth(), image1.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
            tmpImg.createGraphics().drawImage(image1, 0, 0, null);
            image1 = tmpImg;
        }
        if (BufferedImage.TYPE_BYTE_BINARY == imgTp2 && imgTp1 != BufferedImage.TYPE_BYTE_BINARY) {

            BufferedImage tmpImg = new BufferedImage(image2.getWidth(), image2.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
            tmpImg.createGraphics().drawImage(image2, 0, 0, null);
            image2 = tmpImg;
        }

//		BufferedImage TmpImg2 = new BufferedImage(image2.getWidth(),
//				image2.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
//		TmpImg2.createGraphics().drawImage(image1, 0, 0, image2.getWidth(),
//				image2.getHeight(), pt.x, pt.y, pt.x + image2.getWidth(),
//				pt.y + image2.getHeight(), null);
//		RenderedImage res = DoAndImg(TmpImg2, image2);

        Graphics2D g2 = image1.createGraphics();
        g2.drawImage(image2, pt.x, pt.y, null);

        return image1;


    }


    private static boolean createTiff(File fTiff, RenderedImage[] images, long[] dpiData, boolean bFax) {
        // //
        if (dpiData == null || dpiData.length != 2 || fTiff == null || images == null || images.length == 0)
            return false;

        RenderedImage img1 = null;
        FileOutputStream out = null;
        boolean bres = false;
        try {
            int iCompress = TIFFEncodeParam.COMPRESSION_GROUP4;
            for (int i = 0; i < images.length; ++i) {
                if (images[i].getColorModel().getPixelSize() > 1) {
                    if (bFax) {
                        images[i] = RGBToBilevel(images[i], true);
                    } else {
                        iCompress = TIFFEncodeParam.COMPRESSION_PACKBITS;
                        break;
                    }
                }
            }
            img1 = images[0];
            out = new FileOutputStream(fTiff);
            TIFFEncodeParam paramEnc = new TIFFEncodeParam();
            paramEnc.setCompression(iCompress);
            ImageEncoder encoder = ImageCodec.createImageEncoder("tiff", out, paramEnc);
            Vector<RenderedImage> lastImgs = new Vector<RenderedImage>();
            if (images.length > 1) {
                for (int i = 1; i < images.length; ++i)
                    lastImgs.add(images[i]);
                paramEnc.setExtraImages(lastImgs.iterator());
            }
            if (dpiData[0] > 0 || dpiData[1] > 0) {
                int fieldCount = 1;
                if (dpiData[0] > 0 && dpiData[1] > 0) {
                    fieldCount = 2;
                }
                fieldCount += 1;
                TIFFField[] tiffFields = new TIFFField[fieldCount];
                int index = 0;
                if (dpiData[0] > 0) {
                    long xdpiArray[][] = new long[1][2];
                    xdpiArray[0] = new long[]{dpiData[0], 1};
                    TIFFField xRes = new TIFFField(TIFFImageDecoder.TIFF_X_RESOLUTION, TIFFField.TIFF_RATIONAL, 1, xdpiArray);
                    tiffFields[index++] = xRes;
                }
                if (dpiData[1] > 0) {
                    long ydpiArray[][] = new long[1][2];
                    ydpiArray[0] = new long[]{dpiData[1], 1};
                    TIFFField yRes = new TIFFField(TIFFImageDecoder.TIFF_Y_RESOLUTION, TIFFField.TIFF_RATIONAL, 1, ydpiArray);
                    tiffFields[index++] = yRes;
                }
                TIFFField fSoft = new TIFFField(0x0131, TIFFField.TIFF_ASCII, 1, new String[]{"bena create"});
                tiffFields[index++] = fSoft;
                paramEnc.setExtraFields(tiffFields);
            }
            encoder.encode(img1);
            bres = true;
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.flush();
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return bres;
    }
}



